package piwan;

import java.nio.FloatBuffer;

import javax.media.opengl.GL;
import javax.media.opengl.glu.GLU;
import javax.media.opengl.glu.GLUquadric;

public class SoldierRenderer {
	private final double coneRadius = .06;
	private final double coneDiameter = coneRadius*2.0;
	private final double coneHeight = 0.075;
	private final int coneSlices = 10, coneStacks = 2;
	private final double maxSpacing = coneDiameter*0.85;
	private final double minSpacing = coneDiameter*0.5;
	private final int minSpacingAt = 10;
	private final int decreaseSpacingFrom = 3;
	private final double spacingDecrement = (maxSpacing - minSpacing) / (minSpacingAt - decreaseSpacingFrom);
	
	private World world;
	private GL gl;
	private GLU glu;
	private GLUquadric quadric;
	private FloatBuffer lightPos = FloatBuffer.wrap(new float[] {-15.0f,15.0f,1.0f,1.0f});
	private FloatBuffer lightAmb = FloatBuffer.wrap(new float[] {0.1f,0.1f,0.1f,1.0f});
	
	public SoldierRenderer(MainWindow win, GameState gs) {
		this.world = gs.getWorld();
		gl = win.getGL();
		glu = win.getGLU();
		quadric = glu.gluNewQuadric();
	}
	
	public void render() {
		gl.glDisable(GL.GL_TEXTURE_2D);
		gl.glEnable(GL.GL_DEPTH_TEST);
		gl.glEnable(GL.GL_LIGHT0);
		gl.glEnable(GL.GL_LIGHTING);
		gl.glEnable(GL.GL_COLOR_MATERIAL);
		gl.glDisable(GL.GL_BLEND);
		gl.glMatrixMode(GL.GL_MODELVIEW);
		gl.glLightfv(GL.GL_LIGHT0,GL.GL_POSITION, lightPos);
		gl.glLightfv(GL.GL_LIGHT0,GL.GL_AMBIENT, lightAmb);
		for(Region r: world.getRegions())
			if( r.isOwned() )
				doBunch(r.getHotspot(),r.getSoldiers(),r.getOwner().getColour());
	}
	
	private double getConeSpacing(int n) {
		
		if(n>=minSpacingAt)
			return minSpacing;
		if(n>decreaseSpacingFrom)
			return maxSpacing - spacingDecrement*(n-decreaseSpacingFrom);
		else
			return maxSpacing;
	}
	
	private void doBunch(Vector2 c, int n, Colour col) {
		gl.glColor4d(col.r, col.g, col.b, col.a);
		if( n==0 ) return;
		
		if( n==1 ) {
			doSoldier(c.x, c.y);
			return;
		}
		int bigRow = (int)Math.ceil(Math.sqrt((double)n));
		int nBigs = n / bigRow;
		int lastRow = n - bigRow*nBigs;
		if( lastRow == 0 ) { // if there's no lastRow, use one of the bigs as the last row
			nBigs--;
			lastRow = bigRow;
		}
		double spacing = getConeSpacing(n);
		double bigWidth = bigRow*spacing;
		double lastRowWidth = lastRow*spacing;
		double bunchHeight = (nBigs+1)*spacing; // the height is given by the number of bigs + 1 for the last row
		
		double bigStartX = c.x - bigWidth/2.0 + coneRadius;
		double bigStartY = c.y - bunchHeight/2.0 + coneRadius;
		for(int i=0; i<nBigs; ++i)
			for(int j=0; j<bigRow; ++j)
				doSoldier(bigStartX + spacing*j, bigStartY + spacing*i);
		
		double lastStartX = c.x - lastRowWidth/2+coneRadius;
		double lastStartY = bigStartY + nBigs*spacing;
		for(int j=0; j<lastRow; ++j)
			doSoldier(lastStartX + spacing*j, lastStartY);
		
	}
	
	private void doSoldier(double x, double y ) {
		gl.glPushMatrix();
		gl.glTranslated(x,0.0,y);
		gl.glRotated(-90.0, 1.0, 0.0, 0.0);
		glu.gluCylinder(quadric, coneRadius, 0.0, coneHeight, coneSlices, coneStacks);
		gl.glPopMatrix();
	}
	
	

}
